home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume26 / shadow / part07 < prev    next >
Encoding:
Text File  |  1991-11-24  |  54.4 KB  |  2,580 lines

  1. Newsgroups: comp.sources.misc
  2. From: jfh@rpp386.Cactus.ORG (John F Haugh II)
  3. Subject:  v26i060:  shadow - Shadow Password Suite, Part07/11
  4. Message-ID: <1991Nov24.185134.20472@sparky.imd.sterling.com>
  5. X-Md4-Signature: 44ff75e892205797906d354d2e99bf09
  6. Date: Sun, 24 Nov 1991 18:51:34 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jfh@rpp386.Cactus.ORG (John F Haugh II)
  10. Posting-number: Volume 26, Issue 60
  11. Archive-name: shadow/part07
  12. Environment: UNIX
  13. Supersedes: shadow-2: Volume 06, Issue 22-24
  14.  
  15. #! /bin/sh
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  19. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  20. # Contents:  copydir.c getdef.c grdbm.c groupmod.c mkpasswd.c port.c
  21. #   shadow.c
  22. # Wrapped by kent@sparky on Sun Nov 24 11:03:43 1991
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 7 (of 11)."'
  26. if test -f 'copydir.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'copydir.c'\"
  28. else
  29.   echo shar: Extracting \"'copydir.c'\" \(7131 characters\)
  30.   sed "s/^X//" >'copydir.c' <<'END_OF_FILE'
  31. X/*
  32. X * Copyright 1991, John F. Haugh II
  33. X * An unpublished work.
  34. X * All rights reserved.
  35. X *
  36. X * Permission is granted to copy and create derivative works for any
  37. X * non-commercial purpose, provided this copyright notice is preserved
  38. X * in all copies of source code, or included in human readable form
  39. X * and conspicuously displayed on all copies of object code or
  40. X * distribution media.
  41. X */
  42. X
  43. X#include <sys/types.h>
  44. X#include <sys/stat.h>
  45. X#include "config.h"
  46. X#ifdef DIR_XENIX
  47. X#include <sys/ndir.h>
  48. X#define DIRECT direct
  49. X#endif
  50. X#ifdef DIR_BSD
  51. X#include <ndir.h>
  52. X#define DIRECT direct
  53. X#endif
  54. X#ifdef DIR_SYSV
  55. X#include <dirent.h>
  56. X#define DIRECT dirent
  57. X#endif
  58. X#include <fcntl.h>
  59. X#include <stdio.h>
  60. X
  61. X#ifndef lint
  62. Xstatic    char    sccsid[] = "@(#)copydir.c    3.1    10:09:26    6/13/91";
  63. X#endif
  64. X
  65. X#ifndef    S_ISDIR
  66. X#define    S_ISDIR(x)    (((x)&S_IFMT)==S_IFDIR)
  67. X#endif
  68. X#ifndef    S_ISREG
  69. X#define    S_ISREG(x)    (((x)&S_IFMT)==S_IFREG)
  70. X#endif
  71. X
  72. Xstatic    char    *src_orig;
  73. Xstatic    char    *dst_orig;
  74. X
  75. Xstruct    link_name {
  76. X    int    ln_dev;
  77. X    int    ln_ino;
  78. X    int    ln_count;
  79. X    char    *ln_name;
  80. X    struct    link_name *ln_next;
  81. X};
  82. Xstatic    struct    link_name *links;
  83. X
  84. X/*
  85. X * remove_link - delete a link from the link list
  86. X */
  87. X
  88. Xvoid
  89. Xremove_link (link)
  90. Xstruct    link_name *link;
  91. X{
  92. X    struct link_name *lp;
  93. X
  94. X    if (links == link) {
  95. X        links = link->ln_next;
  96. X        free (link->ln_name);
  97. X        free (link);
  98. X        return;
  99. X    }
  100. X    for (lp = links;lp;lp = lp->ln_next)
  101. X        if (lp->ln_next == link)
  102. X            break;
  103. X
  104. X    if (! lp)
  105. X        return;
  106. X
  107. X    lp->ln_next = lp->ln_next->ln_next;
  108. X    free (link->ln_name);
  109. X    free (link);
  110. X}
  111. X
  112. X/*
  113. X * check_link - see if a file is really a link
  114. X */
  115. X
  116. Xstruct link_name *
  117. Xcheck_link (name, sb)
  118. Xchar    *name;
  119. Xstruct    stat    *sb;
  120. X{
  121. X    struct    link_name *lp;
  122. X    int    src_len;
  123. X    int    dst_len;
  124. X    int    name_len;
  125. X    char    *malloc ();
  126. X
  127. X    for (lp = links;lp;lp = lp->ln_next)
  128. X        if (lp->ln_dev == sb->st_dev && lp->ln_ino == sb->st_ino)
  129. X            return lp;
  130. X
  131. X    if (sb->st_nlink == 1)
  132. X        return 0;
  133. X
  134. X    lp = (struct link_name *) malloc (sizeof *lp);
  135. X    src_len = strlen (src_orig);
  136. X    dst_len = strlen (dst_orig);
  137. X    name_len = strlen (name);
  138. X    lp->ln_dev = sb->st_dev;
  139. X    lp->ln_ino = sb->st_ino;
  140. X    lp->ln_count = sb->st_nlink;
  141. X    lp->ln_name = malloc (name_len - src_len + dst_len + 1);
  142. X    sprintf (lp->ln_name, "%s%s", dst_orig, name + src_len);
  143. X    lp->ln_next = links;
  144. X    links = lp;
  145. X
  146. X    return 0;
  147. X}
  148. X
  149. X/*
  150. X * copy_tree - copy files in a directory tree
  151. X *
  152. X *    copy_tree() walks a directory tree and copies ordinary files
  153. X *    as it goes.
  154. X */
  155. X
  156. Xint
  157. Xcopy_tree (src_root, dst_root, uid, gid)
  158. Xchar    *src_root;
  159. Xchar    *dst_root;
  160. Xint    uid;
  161. Xint    gid;
  162. X{
  163. X    char    src_name[BUFSIZ];
  164. X    char    dst_name[BUFSIZ];
  165. X    char    buf[BUFSIZ];
  166. X    int    ifd;
  167. X    int    ofd;
  168. X    int    err = 0;
  169. X    int    cnt;
  170. X    int    set_orig = 0;
  171. X    struct    DIRECT    *ent;
  172. X    struct    stat    sb;
  173. X    struct    link_name *lp;
  174. X    DIR    *dir;
  175. X
  176. X    /*
  177. X     * Make certain both directories exist.  This routine is called
  178. X     * after the home directory is created, or recursively after the
  179. X     * target is created.  It assumes the target directory exists.
  180. X     */
  181. X
  182. X    if (access (src_root, 0) != 0 || access (dst_root, 0) != 0)
  183. X        return -1;
  184. X
  185. X    /*
  186. X     * Open the source directory and read each entry.  Every file
  187. X     * entry in the directory is copied with the UID and GID set
  188. X     * to the provided values.  As an added security feature only
  189. X     * regular files (and directories ...) are copied, and no file
  190. X     * is made set-ID.
  191. X     */
  192. X
  193. X    if (! (dir = opendir (src_root)))
  194. X        return -1;
  195. X
  196. X    if (src_orig == 0) {
  197. X        src_orig = src_root;
  198. X        dst_orig = dst_root;
  199. X        set_orig++;
  200. X    }
  201. X    while (ent = readdir (dir)) {
  202. X
  203. X        /*
  204. X         * Skip the "." and ".." entries
  205. X         */
  206. X
  207. X        if (strcmp (ent->d_name, ".") == 0 ||
  208. X                strcmp (ent->d_name, "..") == 0)
  209. X            continue;
  210. X
  211. X        /*
  212. X         * Make the filename for both the source and the
  213. X         * destination files.
  214. X         */
  215. X
  216. X        if (strlen (src_root) + strlen (ent->d_name) + 2 > BUFSIZ) {
  217. X            err++;
  218. X            break;
  219. X        }
  220. X        sprintf (src_name, "%s/%s", src_root, ent->d_name);
  221. X
  222. X        if (strlen (dst_root) + strlen (ent->d_name) + 2 > BUFSIZ) {
  223. X            err++;
  224. X            break;
  225. X        }
  226. X        sprintf (dst_name, "%s/%s", dst_root, ent->d_name);
  227. X
  228. X        if (stat (src_name, &sb) == -1)
  229. X            continue;
  230. X
  231. X        if (S_ISDIR (sb.st_mode)) {
  232. X
  233. X            /*
  234. X             * Create a new target directory, make it owned by
  235. X             * the user and then recursively copy that directory.
  236. X             */
  237. X
  238. X            mkdir (dst_name, sb.st_mode & 0777);
  239. X            chown (dst_name, uid == -1 ? sb.st_uid:uid,
  240. X                gid == -1 ? sb.st_gid:gid);
  241. X
  242. X            if (copy_tree (src_name, dst_name, uid, gid)) {
  243. X                err++;
  244. X                break;
  245. X            }
  246. X            continue;
  247. X        }
  248. X
  249. X        /*
  250. X         * See if this is a previously copied link
  251. X         */
  252. X
  253. X        if (lp = check_link (src_name, &sb)) {
  254. X            if (link (lp->ln_name, dst_name)) {
  255. X                err++;
  256. X                break;
  257. X            }
  258. X            if (unlink (src_name)) {
  259. X                err++;
  260. X                break;
  261. X            }
  262. X            if (--lp->ln_count <= 0)
  263. X                remove_link (lp);
  264. X
  265. X            continue;
  266. X        }
  267. X
  268. X        /*
  269. X         * Deal with FIFOs and special files.  The user really
  270. X         * shouldn't have any of these, but it seems like it
  271. X         * would be nice to copy everything ...
  272. X         */
  273. X
  274. X        if (! S_ISREG (sb.st_mode)) {
  275. X            if (mknod (dst_name, sb.st_mode & ~07777, sb.st_rdev) ||
  276. X                chown (dst_name, uid == -1 ? sb.st_uid:uid,
  277. X                    gid == -1 ? sb.st_gid:gid) ||
  278. X                    chmod (dst_name, sb.st_mode & 07777)) {
  279. X                err++;
  280. X                break;
  281. X            }
  282. X            continue;
  283. X        }
  284. X
  285. X        /*
  286. X         * Create the new file and copy the contents.  The new
  287. X         * file will be owned by the provided UID and GID values.
  288. X         */
  289. X
  290. X        if ((ifd = open (src_name, O_RDONLY)) < 0) {
  291. X            err++;
  292. X            break;
  293. X        }
  294. X        if ((ofd = open (dst_name, O_WRONLY|O_CREAT, 0)) < 0 ||
  295. X            chown (dst_name, uid == -1 ? sb.st_uid:uid,
  296. X                    gid == -1 ? sb.st_gid:gid) ||
  297. X                chmod (dst_name, sb.st_mode & 07777)) {
  298. X            close (ifd);
  299. X            err++;
  300. X            break;
  301. X        }
  302. X        while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
  303. X            if (write (ofd, buf, cnt) != cnt) {
  304. X                cnt = -1;
  305. X                break;
  306. X            }
  307. X        }
  308. X        close (ifd);
  309. X        close (ofd);
  310. X
  311. X        if (cnt == -1) {
  312. X            err++;
  313. X            break;
  314. X        }
  315. X    }
  316. X    closedir (dir);
  317. X
  318. X    if (set_orig) {
  319. X        src_orig = 0;
  320. X        dst_orig = 0;
  321. X    }
  322. X    return err ? -1:0;
  323. X}
  324. X
  325. X/*
  326. X * remove_tree - remove files in a directory tree
  327. X *
  328. X *    remove_tree() walks a directory tree and deletes all the files
  329. X *    and directories.
  330. X */
  331. X
  332. Xint
  333. Xremove_tree (root)
  334. Xchar    *root;
  335. X{
  336. X    char    new_name[BUFSIZ];
  337. X    int    err = 0;
  338. X    struct    DIRECT    *ent;
  339. X    struct    stat    sb;
  340. X    DIR    *dir;
  341. X
  342. X    /*
  343. X     * Make certain the directory exists.
  344. X     */
  345. X
  346. X    if (access (root, 0) != 0)
  347. X        return -1;
  348. X
  349. X    /*
  350. X     * Open the source directory and read each entry.  Every file
  351. X     * entry in the directory is copied with the UID and GID set
  352. X     * to the provided values.  As an added security feature only
  353. X     * regular files (and directories ...) are copied, and no file
  354. X     * is made set-ID.
  355. X     */
  356. X
  357. X    dir = opendir (root);
  358. X
  359. X    while (ent = readdir (dir)) {
  360. X
  361. X        /*
  362. X         * Skip the "." and ".." entries
  363. X         */
  364. X
  365. X        if (strcmp (ent->d_name, ".") == 0 ||
  366. X                strcmp (ent->d_name, "..") == 0)
  367. X            continue;
  368. X
  369. X        /*
  370. X         * Make the filename for the current entry.
  371. X         */
  372. X
  373. X        if (strlen (root) + strlen (ent->d_name) + 2 > BUFSIZ) {
  374. X            err++;
  375. X            break;
  376. X        }
  377. X        sprintf (new_name, "%s/%s", root, ent->d_name);
  378. X        if (stat (new_name, &sb) == -1)
  379. X            continue;
  380. X
  381. X        if (S_ISDIR (sb.st_mode)) {
  382. X
  383. X            /*
  384. X             * Recursively delete this directory.
  385. X             */
  386. X
  387. X            if (remove_tree (new_name)) {
  388. X                err++;
  389. X                break;
  390. X            }
  391. X            if (rmdir (new_name)) {
  392. X                err++;
  393. X                break;
  394. X            }
  395. X            continue;
  396. X        }
  397. X        unlink (new_name);
  398. X    }
  399. X    closedir (dir);
  400. X
  401. X    return err ? -1:0;
  402. X}
  403. END_OF_FILE
  404.   if test 7131 -ne `wc -c <'copydir.c'`; then
  405.     echo shar: \"'copydir.c'\" unpacked with wrong size!
  406.   fi
  407.   # end of 'copydir.c'
  408. fi
  409. if test -f 'getdef.c' -a "${1}" != "-c" ; then 
  410.   echo shar: Will not clobber existing file \"'getdef.c'\"
  411. else
  412.   echo shar: Extracting \"'getdef.c'\" \(6898 characters\)
  413.   sed "s/^X//" >'getdef.c' <<'END_OF_FILE'
  414. X/*
  415. X * Copyright 1991, John F. Haugh II and Chip Rosenthal
  416. X * All rights reserved.
  417. X *
  418. X * Permission is granted to copy and create derivative works for any
  419. X * non-commercial purpose, provided this copyright notice is preserved
  420. X * in all copies of source code, or included in human readable form
  421. X * and conspicuously displayed on all copies of object code or
  422. X * distribution media.
  423. X */
  424. X
  425. X#ifndef lint
  426. Xstatic    char    sccsid[] = "@(#)getdef.c    3.2    20:54:06    9/18/91";
  427. X#endif
  428. X
  429. X#include <stdio.h>
  430. X#include <ctype.h>
  431. X#ifndef BSD
  432. X# include <string.h>
  433. X#else
  434. X# include <strings.h>
  435. X#endif
  436. X#include "config.h"
  437. X
  438. X#ifdef    USE_SYSLOG
  439. X#include <syslog.h>
  440. X
  441. X#ifndef    LOG_WARN
  442. X#define    LOG_WARN    LOG_WARNING
  443. X#endif
  444. X#endif
  445. X
  446. X/*
  447. X * A configuration item definition.
  448. X */
  449. X
  450. Xstruct itemdef {
  451. X    char *name;        /* name of the item            */
  452. X    char *value;        /* value given, or NULL if no value    */
  453. X};
  454. X
  455. X/*
  456. X * This list *must* be sorted by the "name" member.
  457. X */
  458. X
  459. X#define NUMDEFS    (sizeof(def_table)/sizeof(def_table[0]))
  460. Xstruct itemdef def_table[] = {
  461. X    { "CONSOLE",            NULL },
  462. X    { "DIALUPS_CHECK_ENAB",        NULL },
  463. X    { "ENV_HZ",            NULL },
  464. X    { "ENV_PATH" ,            NULL },
  465. X    { "ENV_SUPATH",            NULL },
  466. X    { "ENV_TZ",            NULL },
  467. X    { "ERASECHAR",            NULL },
  468. X    { "FAILLOG_ENAB",        NULL },
  469. X    { "FTMP_FILE",            NULL },
  470. X    { "HUSHLOGIN_FILE",        NULL },
  471. X    { "ISSUE_FILE_ENAB",        NULL },
  472. X    { "KILLCHAR",            NULL },
  473. X    { "LASTLOG_ENAB",        NULL },
  474. X    { "LOG_UNKFAIL_ENAB",        NULL },
  475. X    { "MAIL_CHECK_ENAB",        NULL },
  476. X    { "MAIL_DIR",            NULL },
  477. X    { "MOTD_FILE",            NULL },
  478. X    { "NOLOGINS_FILE",        NULL },
  479. X    { "NOLOGIN_STR",        NULL },
  480. X    { "OBSCURE_CHECKS_ENAB",    NULL },
  481. X    { "PASS_MAX_DAYS",        NULL },
  482. X    { "PASS_MIN_DAYS",        NULL },
  483. X    { "PASS_MIN_LEN",        NULL },
  484. X    { "PASS_WARN_AGE",        NULL },
  485. X    { "PORTTIME_CHECKS_ENAB",    NULL },
  486. X    { "QUOTAS_ENAB",        NULL },
  487. X    { "SULOG_FILE",            NULL },
  488. X    { "SYSLOG_SU_ENAB",        NULL },
  489. X    { "TTYPERM",            NULL },
  490. X    { "TTYTYPE_FILE",        NULL },
  491. X    { "ULIMIT",            NULL },
  492. X    { "UMASK",            NULL },
  493. X};
  494. X
  495. Xstatic char def_fname[] = LOGINDEFS;    /* login config defs file    */
  496. Xstatic int def_loaded = 0;        /* are defs already loaded?    */
  497. X
  498. Xextern long strtol();
  499. X
  500. Xstatic struct itemdef *def_find();
  501. Xstatic void def_load();
  502. X
  503. X
  504. X/*
  505. X * getdef_str - get string value from table of definitions.
  506. X *
  507. X * Return point to static data for specified item, or NULL if item is not
  508. X * defined.  First time invoked, will load definitions from the file.
  509. X */
  510. X
  511. Xchar *
  512. Xgetdef_str(item)
  513. Xchar *item;
  514. X{
  515. X    struct itemdef *d;
  516. X
  517. X    if (!def_loaded)
  518. X        def_load();
  519. X
  520. X    return ((d = def_find(item)) == NULL ? (char *)NULL : d->value);
  521. X}
  522. X
  523. X
  524. X/*
  525. X * getdef_bool - get boolean value from table of definitions.
  526. X *
  527. X * Return TRUE if specified item is defined as "yes", else FALSE.
  528. X */
  529. X
  530. Xint
  531. Xgetdef_bool(item)
  532. Xchar *item;
  533. X{
  534. X    struct itemdef *d;
  535. X
  536. X    if (!def_loaded)
  537. X        def_load();
  538. X
  539. X    if ((d = def_find(item)) == NULL || d->value == NULL)
  540. X        return 0;
  541. X
  542. X    return (strcmp(d->value, "yes") == 0);
  543. X}
  544. X
  545. X
  546. X/*
  547. X * getdef_num - get numerical value from table of definitions
  548. X *
  549. X * Returns numeric value of specified item, else the "dflt" value if
  550. X * the item is not defined.  Octal (leading "0") and hex (leading "0x")
  551. X * values are handled.
  552. X */
  553. X
  554. Xint
  555. Xgetdef_num(item, dflt)
  556. Xchar *item;
  557. Xint dflt;
  558. X{
  559. X    struct itemdef *d;
  560. X
  561. X    if (!def_loaded)
  562. X        def_load();
  563. X
  564. X    if ((d = def_find(item)) == NULL || d->value == NULL)
  565. X        return dflt;
  566. X
  567. X    return (int) strtol(d->value, (char **)NULL, 0);
  568. X}
  569. X
  570. X
  571. X/*
  572. X * getdef_long - get long integer value from table of definitions
  573. X *
  574. X * Returns numeric value of specified item, else the "dflt" value if
  575. X * the item is not defined.  Octal (leading "0") and hex (leading "0x")
  576. X * values are handled.
  577. X */
  578. X
  579. Xlong
  580. Xgetdef_long(item, dflt)
  581. Xchar *item;
  582. Xlong dflt;
  583. X{
  584. X    struct itemdef *d;
  585. X
  586. X    if (!def_loaded)
  587. X        def_load();
  588. X
  589. X    if ((d = def_find(item)) == NULL || d->value == NULL)
  590. X        return dflt;
  591. X
  592. X    return strtol(d->value, (char **)NULL, 0);
  593. X}
  594. X
  595. X/*
  596. X * def_find - locate named item in table
  597. X *
  598. X * Search through a sorted table of configurable items to locate the
  599. X * specified configuration option.
  600. X */
  601. X
  602. Xstatic struct itemdef *
  603. Xdef_find(name)
  604. Xchar *name;
  605. X{
  606. X    int min, max, curr, n;
  607. X
  608. X    /*
  609. X     * Invariant - desired item in range [min:max].
  610. X     */
  611. X
  612. X    min = 0;
  613. X    max = NUMDEFS-1;
  614. X
  615. X    /*
  616. X     * Binary search into the table.  Relies on the items being
  617. X     * sorted by name.
  618. X     */
  619. X
  620. X    while (min <= max) {
  621. X        curr = (min+max)/2;
  622. X
  623. X        if (! (n = strcmp(def_table[curr].name, name)))
  624. X            return &def_table[curr];
  625. X
  626. X        if (n < 0)
  627. X            min = curr+1;
  628. X        else
  629. X            max = curr-1;
  630. X    }
  631. X
  632. X    /*
  633. X     * Item was never found.
  634. X     */
  635. X
  636. X    fprintf(stderr, "configuration error - unknown item '%s' (notify administrator)\r\n", name);
  637. X#ifdef USE_SYSLOG
  638. X    syslog(LOG_CRIT, "unknown configuration item `%s'", name);
  639. X#endif
  640. X    return (struct itemdef *) NULL;
  641. X}
  642. X
  643. X/*
  644. X * def_load - load configuration table
  645. X *
  646. X * Loads the user-configured options from the default configuration file
  647. X */
  648. X
  649. Xstatic void
  650. Xdef_load()
  651. X{
  652. X    int i;
  653. X    FILE *fp;
  654. X    struct itemdef *d;
  655. X    char buf[BUFSIZ], *name, *value, *s;
  656. X
  657. X#ifdef CKDEFS
  658. X
  659. X    /*
  660. X     * Set this flag early so the errors will be reported only
  661. X     * during testing.
  662. X     */
  663. X
  664. X    ++def_loaded;
  665. X#endif
  666. X
  667. X    /*
  668. X     * Open the configuration definitions file.
  669. X     */
  670. X
  671. X    if ((fp = fopen(def_fname, "r")) == NULL) {
  672. X#ifdef USE_SYSLOG
  673. X        extern int errno;
  674. X        extern char *sys_errlist[];
  675. X
  676. X        syslog(LOG_CRIT, "cannot open login definitions %s [%s]",
  677. X            def_fname, sys_errlist[errno]);
  678. X#endif
  679. X        return;
  680. X    }
  681. X
  682. X    /*
  683. X     * Go through all of the lines in the file.
  684. X     */
  685. X
  686. X    while (fgets(buf, sizeof(buf), fp) != NULL) {
  687. X
  688. X        /*
  689. X         * Trim trailing whitespace.
  690. X         */
  691. X
  692. X        for (i = strlen(buf)-1 ; i >= 0 ; --i) {
  693. X            if (!isspace(buf[i]))
  694. X                break;
  695. X        }
  696. X        buf[++i] = '\0';
  697. X
  698. X        /*
  699. X         * Break the line into two fields.
  700. X         */
  701. X
  702. X        name = buf + strspn(buf, " \t");    /* first nonwhite */
  703. X        if (*name == '\0' || *name == '#')
  704. X            continue;            /* comment or empty */
  705. X
  706. X        s = name + strcspn(name, " \t");    /* end of field */
  707. X        if (*s == '\0')
  708. X            continue;            /* only 1 field?? */
  709. X
  710. X        *s++ = '\0';
  711. X        value = s + strspn(s, " \t");        /* next nonwhite */
  712. X
  713. X        /*
  714. X         * Locate the slot to save the value.  If this parameter
  715. X         * is unknown then "def_find" will print an err message.
  716. X         */
  717. X
  718. X        if ((d = def_find(name)) == NULL)
  719. X            continue;
  720. X
  721. X        /*
  722. X         * Save off the value.
  723. X         */
  724. X
  725. X        if ((d->value = strdup(value)) == NULL) {
  726. X            if (! def_loaded)
  727. X                break;
  728. X
  729. X            fputs("Could not allocate space for config info.\r\n", stderr);
  730. X#ifndef CKDEFS
  731. X#ifdef USE_SYSLOG
  732. X            syslog(LOG_ERR, "could not allocate space for config info");
  733. X#endif
  734. X#endif
  735. X            break;
  736. X        }
  737. X    }
  738. X    (void) fclose(fp);
  739. X
  740. X    /*
  741. X     * Set the initialized flag.
  742. X     */
  743. X
  744. X    ++def_loaded;
  745. X}
  746. X
  747. X#ifdef CKDEFS
  748. Xmain(argc, argv)
  749. Xint    argc;
  750. Xchar    **argv;
  751. X{
  752. X    int i;
  753. X    char *cp;
  754. X    struct itemdef *d;
  755. X
  756. X    def_load ();
  757. X
  758. X    for (i = 0 ; i < NUMDEFS ; ++i) {
  759. X        if ((d = def_find(def_table[i].name)) == NULL)
  760. X            printf("error - lookup '%s' failed\n", def_table[i].name);
  761. X        else
  762. X            printf("%4d %-24s %s\n", i+1, d->name, d->value);
  763. X    }
  764. X    for (i = 1;i < argc;i++) {
  765. X        if (cp = getdef_str (argv[1]))
  766. X            printf ("%s `%s'\n", argv[1], cp);
  767. X        else
  768. X            printf ("%s not found\n", argv[1]);
  769. X    }
  770. X    exit(0);
  771. X}
  772. X#endif
  773. END_OF_FILE
  774.   if test 6898 -ne `wc -c <'getdef.c'`; then
  775.     echo shar: \"'getdef.c'\" unpacked with wrong size!
  776.   fi
  777.   # end of 'getdef.c'
  778. fi
  779. if test -f 'grdbm.c' -a "${1}" != "-c" ; then 
  780.   echo shar: Will not clobber existing file \"'grdbm.c'\"
  781. else
  782.   echo shar: Extracting \"'grdbm.c'\" \(3618 characters\)
  783.   sed "s/^X//" >'grdbm.c' <<'END_OF_FILE'
  784. X/*
  785. X * Copyright 1990, 1991, John F. Haugh II
  786. X * All rights reserved.
  787. X *
  788. X * Use, duplication, and disclosure prohibited without
  789. X * the express written permission of the author.
  790. X */
  791. X
  792. X#ifndef    lint
  793. Xstatic    char    sccsid[] = "@(#)grdbm.c    3.3    08:44:03    9/12/91";
  794. X#endif
  795. X
  796. X#include <string.h>
  797. X#include <stdio.h>
  798. X#include <grp.h>
  799. X#include "config.h"
  800. X
  801. X#ifdef    NDBM
  802. X#include <ndbm.h>
  803. XDBM    *gr_dbm;
  804. X
  805. X#define    GRP_FRAG    256
  806. X
  807. X/*
  808. X * gr_dbm_update
  809. X *
  810. X * Updates the DBM password files, if they exist.
  811. X */
  812. X
  813. Xint
  814. Xgr_dbm_update (gr)
  815. Xstruct    group    *gr;
  816. X{
  817. X    datum    key;
  818. X    datum    content;
  819. X    char    data[BUFSIZ*8];
  820. X    char    grpkey[60];
  821. X    char    *cp;
  822. X    int    len;
  823. X    int    i;
  824. X    int    cnt;
  825. X    static    int    once;
  826. X
  827. X    if (! once) {
  828. X        if (! gr_dbm)
  829. X            setgrent ();
  830. X
  831. X        once++;
  832. X    }
  833. X    if (! gr_dbm)
  834. X        return 0;
  835. X
  836. X    len = gr_pack (gr, data);
  837. X
  838. X    if (len <= GRP_FRAG) {
  839. X        content.dsize = len;
  840. X        content.dptr = data;
  841. X
  842. X        key.dsize = strlen (gr->gr_name);
  843. X        key.dptr = gr->gr_name;
  844. X        if (dbm_store (gr_dbm, key, content, DBM_REPLACE))
  845. X            return 0;
  846. X
  847. X        key.dsize = sizeof gr->gr_gid;
  848. X        key.dptr = (char *) &gr->gr_gid;
  849. X        if (dbm_store (gr_dbm, key, content, DBM_REPLACE))
  850. X            return 0;
  851. X
  852. X    } else {
  853. X        content.dsize = sizeof cnt;
  854. X        content.dptr = (char *) &cnt;
  855. X        cnt = (len + (GRP_FRAG-1)) / GRP_FRAG;
  856. X
  857. X        key.dsize = strlen (gr->gr_name);
  858. X        key.dptr = gr->gr_name;
  859. X        if (dbm_store (gr_dbm, key, content, DBM_REPLACE))
  860. X            return 0;
  861. X
  862. X        key.dsize = sizeof gr->gr_gid;
  863. X        key.dptr = (char *) &gr->gr_gid;
  864. X        if (dbm_store (gr_dbm, key, content, DBM_REPLACE))
  865. X            return 0;
  866. X
  867. X        for (cp = data, i = 0;i < cnt;i++) {
  868. X            content.dsize = len > GRP_FRAG ? GRP_FRAG:len;
  869. X            len -= content.dsize;
  870. X            content.dptr = cp;
  871. X            cp += content.dsize;
  872. X
  873. X            key.dsize = sizeof i + strlen (gr->gr_name);
  874. X            key.dptr = grpkey;
  875. X            memcpy (grpkey, (char *) &i, sizeof i);
  876. X            strcpy (grpkey + sizeof i, gr->gr_name);
  877. X            if (dbm_store (gr_dbm, key, content, DBM_REPLACE))
  878. X                return 0;
  879. X
  880. X            key.dsize = sizeof i + sizeof gr->gr_gid;
  881. X            key.dptr = grpkey;
  882. X            memcpy (grpkey, (char *) &i, sizeof i);
  883. X            memcpy (grpkey + sizeof i, (char *) &gr->gr_gid,
  884. X                sizeof gr->gr_gid);
  885. X            if (dbm_store (gr_dbm, key, content, DBM_REPLACE))
  886. X                return 0;
  887. X        }
  888. X    }
  889. X    return 1;
  890. X}
  891. X
  892. X/*
  893. X * gr_dbm_remove
  894. X *
  895. X * Deletes the DBM group file entries, if they exist.
  896. X */
  897. X
  898. Xint
  899. Xgr_dbm_remove (gr)
  900. Xstruct    group    *gr;
  901. X{
  902. X    datum    key;
  903. X    datum    content;
  904. X    char    grpkey[60];
  905. X    int    i;
  906. X    int    cnt;
  907. X    int    errors = 0;
  908. X    static    int    once;
  909. X
  910. X    if (! once) {
  911. X        if (! gr_dbm)
  912. X            setgrent ();
  913. X
  914. X        once++;
  915. X    }
  916. X    if (! gr_dbm)
  917. X        return 0;
  918. X
  919. X    key.dsize = strlen (gr->gr_name);
  920. X    key.dptr = (char *) gr->gr_name;
  921. X    content = dbm_fetch (gr_dbm, key);
  922. X    if (content.dptr == 0)
  923. X        ++errors;
  924. X    else {
  925. X        if (content.dsize == sizeof (int)) {
  926. X            memcpy ((char *) &cnt, content.dptr, sizeof cnt);
  927. X
  928. X            for (i = 0;i < cnt;i++) {
  929. X                key.dsize = sizeof i + strlen (gr->gr_name);
  930. X                key.dptr = grpkey;
  931. X                memcpy (grpkey, (char *) &i, sizeof i);
  932. X                strcpy (grpkey + sizeof i, gr->gr_name);
  933. X                if (dbm_delete (gr_dbm, key))
  934. X                    ++errors;
  935. X            }
  936. X        } else {
  937. X            if (dbm_delete (gr_dbm, key))
  938. X                ++errors;
  939. X        }
  940. X    }
  941. X    key.dsize = sizeof gr->gr_gid;
  942. X    key.dptr = (char *) &gr->gr_gid;
  943. X    content = dbm_fetch (gr_dbm, key);
  944. X    if (content.dptr == 0)
  945. X        ++errors;
  946. X    else {
  947. X        if (content.dsize == sizeof (int)) {
  948. X            memcpy ((char *) &cnt, content.dptr, sizeof cnt);
  949. X
  950. X            for (i = 0;i < cnt;i++) {
  951. X                key.dsize = sizeof i + sizeof gr->gr_gid;
  952. X                key.dptr = grpkey;
  953. X                memcpy (grpkey, (char *) &i, sizeof i);
  954. X                memcpy (grpkey + sizeof i, (char *) &gr->gr_gid,
  955. X                    sizeof gr->gr_gid);
  956. X
  957. X                if (dbm_delete (gr_dbm, key))
  958. X                    ++errors;
  959. X            }
  960. X        } else {
  961. X            if (dbm_delete (gr_dbm, key))
  962. X                ++errors;
  963. X        }
  964. X    }
  965. X    return errors ? 0:1;
  966. X}
  967. X#endif
  968. END_OF_FILE
  969.   if test 3618 -ne `wc -c <'grdbm.c'`; then
  970.     echo shar: \"'grdbm.c'\" unpacked with wrong size!
  971.   fi
  972.   # end of 'grdbm.c'
  973. fi
  974. if test -f 'groupmod.c' -a "${1}" != "-c" ; then 
  975.   echo shar: Will not clobber existing file \"'groupmod.c'\"
  976. else
  977.   echo shar: Extracting \"'groupmod.c'\" \(8138 characters\)
  978.   sed "s/^X//" >'groupmod.c' <<'END_OF_FILE'
  979. X/*
  980. X * Copyright 1991, John F. Haugh II
  981. X * All rights reserved.
  982. X *
  983. X * Permission is granted to copy and create derivative works for any
  984. X * non-commercial purpose, provided this copyright notice is preserved
  985. X * in all copies of source code, or included in human readable form
  986. X * and conspicuously displayed on all copies of object code or
  987. X * distribution media.
  988. X */
  989. X
  990. X#ifndef lint
  991. Xstatic    char    sccsid[] = "@(#)groupmod.c    3.3    08:43:51    9/12/91";
  992. X#endif
  993. X
  994. X#include <sys/types.h>
  995. X#include <stdio.h>
  996. X#include <grp.h>
  997. X#include <ctype.h>
  998. X#include <fcntl.h>
  999. X
  1000. X#ifdef    BSD
  1001. X#include <strings.h>
  1002. X#else
  1003. X#include <string.h>
  1004. X#endif
  1005. X
  1006. X#include "config.h"
  1007. X#include "shadow.h"
  1008. X
  1009. X#ifdef    USE_SYSLOG
  1010. X#include <syslog.h>
  1011. X#endif
  1012. X
  1013. Xchar    group_name[BUFSIZ];
  1014. Xchar    group_newname[BUFSIZ];
  1015. Xint    group_id;
  1016. Xint    group_newid;
  1017. X
  1018. Xchar    *Prog;
  1019. X
  1020. Xint    oflg;    /* permit non-unique group ID to be specified with -g         */
  1021. Xint    gflg;    /* new ID value for the group                                 */
  1022. Xint    nflg;    /* a new name has been specified for the group                */
  1023. X
  1024. X#ifdef    NDBM
  1025. Xextern    int    gr_dbm_mode;
  1026. Xextern    int    sg_dbm_mode;
  1027. X#endif
  1028. Xextern    char    *malloc();
  1029. X
  1030. Xextern    struct    group    *getgrnam();
  1031. Xextern    struct    group    *gr_next();
  1032. Xextern    struct    group    *gr_locate();
  1033. Xextern    int    gr_lock();
  1034. Xextern    int    gr_unlock();
  1035. Xextern    int    gr_rewind();
  1036. Xextern    int    gr_open();
  1037. X
  1038. X#ifdef    SHADOWGRP
  1039. Xextern    struct    sgrp    *sgr_locate();
  1040. Xextern    int    sgr_lock();
  1041. Xextern    int    sgr_unlock();
  1042. Xextern    int    sgr_open();
  1043. X#endif
  1044. X
  1045. X/*
  1046. X * usage - display usage message and exit
  1047. X */
  1048. X
  1049. Xusage ()
  1050. X{
  1051. X    fprintf (stderr, "usage: groupmod [-g gid [-o]] [-n name] group\n");
  1052. X    exit (2);
  1053. X}
  1054. X
  1055. X/*
  1056. X * new_grent - updates the values in a group file entry
  1057. X *
  1058. X *    new_grent() takes all of the values that have been entered and
  1059. X *    fills in a (struct group) with them.
  1060. X */
  1061. X
  1062. Xvoid
  1063. Xnew_grent (grent)
  1064. Xstruct    group    *grent;
  1065. X{
  1066. X    if (nflg)
  1067. X        grent->gr_name = strdup (group_newname);
  1068. X
  1069. X    if (gflg)
  1070. X        grent->gr_gid = group_newid;
  1071. X}
  1072. X
  1073. X#ifdef    SHADOWGRP
  1074. X/*
  1075. X * new_sgent - updates the values in a shadow group file entry
  1076. X *
  1077. X *    new_sgent() takes all of the values that have been entered and
  1078. X *    fills in a (struct sgrp) with them.
  1079. X */
  1080. X
  1081. Xvoid
  1082. Xnew_sgent (sgent)
  1083. Xstruct    sgrp    *sgent;
  1084. X{
  1085. X    if (nflg)
  1086. X        sgent->sg_name = strdup (group_newname);
  1087. X}
  1088. X#endif    /* SHADOWGRP */
  1089. X
  1090. X/*
  1091. X * grp_update - update group file entries
  1092. X *
  1093. X *    grp_update() writes the new records to the group files.
  1094. X */
  1095. X
  1096. Xvoid
  1097. Xgrp_update ()
  1098. X{
  1099. X    struct    group    grp;
  1100. X    struct    group    *ogrp;
  1101. X#ifdef    SHADOWGRP
  1102. X    struct    sgrp    sgrp;
  1103. X#endif    /* SHADOWGRP */
  1104. X
  1105. X    /*
  1106. X     * Create the initial entries for this new group.
  1107. X     */
  1108. X
  1109. X    grp = *(gr_locate (group_name));
  1110. X    new_grent (&grp);
  1111. X#ifdef    SHADOWGRP
  1112. X    sgrp = *(sgr_locate (group_name));
  1113. X    new_sgent (&sgrp);
  1114. X#endif    /* SHADOWGRP */
  1115. X
  1116. X    /*
  1117. X     * Write out the new group file entry.
  1118. X     */
  1119. X
  1120. X    if (! gr_update (&grp)) {
  1121. X        fprintf (stderr, "%s: error adding new group entry\n", Prog);
  1122. X        exit (1);
  1123. X    }
  1124. X    if (nflg && ! gr_remove (group_name)) {
  1125. X        fprintf (stderr, "%s: error removing group entry\n", Prog);
  1126. X        exit (1);
  1127. X    }
  1128. X#ifdef    NDBM
  1129. X
  1130. X    /*
  1131. X     * Update the DBM group file with the new entry as well.
  1132. X     */
  1133. X
  1134. X    if (access ("/etc/group.pag", 0) == 0) {
  1135. X        if (! gr_dbm_update (&grp)) {
  1136. X            fprintf (stderr, "%s: cannot add new dbm group entry\n",
  1137. X                Prog);
  1138. X            exit (1);
  1139. X        }
  1140. X        if (nflg && (ogrp = getgrnam (group_name)) &&
  1141. X                ! gr_dbm_remove (ogrp)) {
  1142. X            fprintf (stderr, "%s: error removing group dbm entry\n",
  1143. X                Prog);
  1144. X            exit (1);
  1145. X        }
  1146. X        endgrent ();
  1147. X    }
  1148. X#endif    /* NDBM */
  1149. X
  1150. X#ifdef    SHADOWGRP
  1151. X
  1152. X    /*
  1153. X     * Write out the new shadow group entries as well.
  1154. X     */
  1155. X
  1156. X    if (! sgr_update (&sgrp)) {
  1157. X        fprintf (stderr, "%s: error adding new group entry\n", Prog);
  1158. X        exit (1);
  1159. X    }
  1160. X    if (nflg && ! sgr_remove (group_name)) {
  1161. X        fprintf (stderr, "%s: error removing group entry\n", Prog);
  1162. X        exit (1);
  1163. X    }
  1164. X#ifdef    NDBM
  1165. X
  1166. X    /*
  1167. X     * Update the DBM shadow group file with the new entry as well.
  1168. X     */
  1169. X
  1170. X    if (access ("/etc/gshadow.pag", 0) == 0) {
  1171. X        if (! sgr_dbm_update (&sgrp)) {
  1172. X            fprintf (stderr,
  1173. X                "%s: cannot add new dbm shadow group entry\n",
  1174. X                Prog);
  1175. X            exit (1);
  1176. X        }
  1177. X        if (nflg && ! sgr_dbm_remove (group_name)) {
  1178. X            fprintf (stderr,
  1179. X                "%s: error removing shadow group dbm entry\n",
  1180. X                Prog);
  1181. X            exit (1);
  1182. X        }
  1183. X        endsgent ();
  1184. X    }
  1185. X#endif    /* NDBM */
  1186. X#endif    /* SHADOWGRP */
  1187. X#ifdef    USE_SYSLOG
  1188. X    if (nflg)
  1189. X        syslog (LOG_INFO, "change group `%s' to `%s'\n",
  1190. X            group_name, group_newname);
  1191. X
  1192. X    if (gflg)
  1193. X        syslog (LOG_INFO, "change gid for `%s' to %d\n",
  1194. X            nflg ? group_name:group_newname, group_newid);
  1195. X#endif    /* USE_SYSLOG */
  1196. X}
  1197. X
  1198. X/*
  1199. X * check_new_gid - check the new GID value for uniqueness
  1200. X *
  1201. X *    check_new_gid() insures that the new GID value is unique.
  1202. X */
  1203. X
  1204. Xint
  1205. Xcheck_new_gid ()
  1206. X{
  1207. X    /*
  1208. X     * First, the easy stuff.  If the ID can be duplicated, or if
  1209. X     * the ID didn't really change, just return.  If the ID didn't
  1210. X     * change, turn off those flags.  No sense doing needless work.
  1211. X     */
  1212. X
  1213. X    if (oflg)
  1214. X        return 0;
  1215. X
  1216. X    if (group_id == group_newid) {
  1217. X        gflg = 0;
  1218. X        return 0;
  1219. X    }
  1220. X    if (getgrgid (group_newid))
  1221. X        return -1;
  1222. X
  1223. X    return 0;
  1224. X}
  1225. X
  1226. X/*
  1227. X * process_flags - perform command line argument setting
  1228. X *
  1229. X *    process_flags() interprets the command line arguments and sets
  1230. X *    the values that the user will be created with accordingly.  The
  1231. X *    values are checked for sanity.
  1232. X */
  1233. X
  1234. Xvoid
  1235. Xprocess_flags (argc, argv)
  1236. Xint    argc;
  1237. Xchar    **argv;
  1238. X{
  1239. X    extern    int    optind;
  1240. X    extern    char    *optarg;
  1241. X    char    *end;
  1242. X    int    arg;
  1243. X
  1244. X    while ((arg = getopt (argc, argv, "og:n:")) != EOF) {
  1245. X        switch (arg) {
  1246. X            case 'g':
  1247. X                gflg++;
  1248. X                group_newid = strtol (optarg, &end, 10);
  1249. X                if (*end != '\0') {
  1250. X                    fprintf (stderr, "%s: invalid group %s\n",
  1251. X                        Prog, optarg);
  1252. X                    exit (3);
  1253. X                }
  1254. X                break;
  1255. X            case 'n':
  1256. X                if (strcmp (group_name, optarg)) {
  1257. X                    nflg++;
  1258. X                    strncpy (group_newname, optarg, BUFSIZ);
  1259. X                }
  1260. X                break;
  1261. X            case 'o':
  1262. X                if (! gflg)
  1263. X                    usage ();
  1264. X
  1265. X                oflg++;
  1266. X                break;
  1267. X            default:
  1268. X                usage ();
  1269. X        }
  1270. X    }
  1271. X    if (optind == argc - 1)
  1272. X        strcpy (group_name, argv[argc - 1]);
  1273. X    else
  1274. X        usage ();
  1275. X}
  1276. X
  1277. X/*
  1278. X * close_files - close all of the files that were opened
  1279. X *
  1280. X *    close_files() closes all of the files that were opened for this
  1281. X *    new group.  This causes any modified entries to be written out.
  1282. X */
  1283. X
  1284. Xclose_files ()
  1285. X{
  1286. X    if (! gr_close ()) {
  1287. X        fprintf (stderr, "%s: cannot rewrite group file\n", Prog);
  1288. X        exit (1);
  1289. X    }
  1290. X    (void) gr_unlock ();
  1291. X#ifdef    SHADOWGRP
  1292. X    if (! sgr_close ()) {
  1293. X        fprintf (stderr, "%s: cannot rewrite shadow group file\n",
  1294. X            Prog);
  1295. X        exit (1);
  1296. X    }
  1297. X    (void) sgr_unlock ();
  1298. X#endif    /* SHADOWGRP */
  1299. X}
  1300. X
  1301. X/*
  1302. X * open_files - lock and open the group files
  1303. X *
  1304. X *    open_files() opens the two group files.
  1305. X */
  1306. X
  1307. Xopen_files ()
  1308. X{
  1309. X    if (! gr_lock ()) {
  1310. X        fprintf (stderr, "%s: unable to lock group file\n", Prog);
  1311. X        exit (1);
  1312. X    }
  1313. X    if (! gr_open (O_RDWR)) {
  1314. X        fprintf (stderr, "%s: unable to open group file\n", Prog);
  1315. X        exit (1);
  1316. X    }
  1317. X#ifdef    SHADOWGRP
  1318. X    if (! sgr_lock ()) {
  1319. X        fprintf (stderr, "%s: unable to lock shadow group file\n",
  1320. X            Prog);
  1321. X        exit (1);
  1322. X    }
  1323. X    if (! sgr_open (O_RDWR)) {
  1324. X        fprintf (stderr, "%s: unable to open shadow group file\n",
  1325. X            Prog);
  1326. X        exit (1);
  1327. X    }
  1328. X#endif    /* SHADOWGRP */
  1329. X}
  1330. X
  1331. X/*
  1332. X * main - groupmod command
  1333. X *
  1334. X *    The syntax of the groupmod command is
  1335. X *    
  1336. X *    groupmod [ -g gid [ -o ]] [ -n name ] group
  1337. X *
  1338. X *    The flags are
  1339. X *        -g - specify a new group ID value
  1340. X *        -o - permit the group ID value to be non-unique
  1341. X *        -n - specify a new group name
  1342. X */
  1343. X
  1344. Xmain (argc, argv)
  1345. Xint    argc;
  1346. Xchar    **argv;
  1347. X{
  1348. X
  1349. X    /*
  1350. X     * Get my name so that I can use it to report errors.
  1351. X     */
  1352. X
  1353. X    if (Prog = strrchr (argv[0], '/'))
  1354. X        Prog++;
  1355. X    else
  1356. X        Prog = argv[0];
  1357. X
  1358. X#ifdef    USE_SYSLOG
  1359. X    openlog (Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
  1360. X#endif    /* USE_SYSLOG */
  1361. X
  1362. X    /*
  1363. X     * The open routines for the DBM files don't use read-write
  1364. X     * as the mode, so we have to clue them in.
  1365. X     */
  1366. X
  1367. X#ifdef    NDBM
  1368. X    gr_dbm_mode = O_RDWR;
  1369. X#ifdef    SHADOWGRP
  1370. X    sg_dbm_mode = O_RDWR;
  1371. X#endif    /* SHADOWGRP */
  1372. X#endif    /* NDBM */
  1373. X    process_flags (argc, argv);
  1374. X
  1375. X    /*
  1376. X     * Start with a quick check to see if the group exists.
  1377. X     */
  1378. X
  1379. X    if (! getgrnam (group_name)) {
  1380. X        fprintf (stderr, "%s: group %s does not exist\n",
  1381. X            Prog, group_name);
  1382. X        exit (9);
  1383. X    }
  1384. X
  1385. X    /*
  1386. X     * Do the hard stuff - open the files, create the group entries,
  1387. X     * then close and update the files.
  1388. X     */
  1389. X
  1390. X    open_files ();
  1391. X
  1392. X    grp_update ();
  1393. X
  1394. X    close_files ();
  1395. X    exit (0);
  1396. X    /*NOTREACHED*/
  1397. X}
  1398. END_OF_FILE
  1399.   if test 8138 -ne `wc -c <'groupmod.c'`; then
  1400.     echo shar: \"'groupmod.c'\" unpacked with wrong size!
  1401.   fi
  1402.   # end of 'groupmod.c'
  1403. fi
  1404. if test -f 'mkpasswd.c' -a "${1}" != "-c" ; then 
  1405.   echo shar: Will not clobber existing file \"'mkpasswd.c'\"
  1406. else
  1407.   echo shar: Extracting \"'mkpasswd.c'\" \(8625 characters\)
  1408.   sed "s/^X//" >'mkpasswd.c' <<'END_OF_FILE'
  1409. X/*
  1410. X * Copyright 1990, 1991, John F. Haugh II
  1411. X * All rights reserved.
  1412. X *
  1413. X * Permission is granted to copy and create derivative works for any
  1414. X * non-commercial purpose, provided this copyright notice is preserved
  1415. X * in all copies of source code, or included in human readable form
  1416. X * and conspicuously displayed on all copies of object code or
  1417. X * distribution media.
  1418. X */
  1419. X
  1420. X#ifndef    lint
  1421. Xstatic    char    sccsid[] = "@(#)mkpasswd.c    3.9    07:44:14    9/17/91";
  1422. Xstatic    char    copyright[] = "Copyright 1990, 1991, John F. Haugh II";
  1423. X#endif
  1424. X
  1425. X#include "config.h"
  1426. X#include <stdio.h>
  1427. X
  1428. X#if !defined(DBM) && !defined(NDBM) /*{*/
  1429. X
  1430. Xmain (argc, argv)
  1431. Xint    argc;
  1432. Xchar    **argv;
  1433. X{
  1434. X    fprintf(stderr, "%s: no DBM database on system - no action performed\n",
  1435. X        argv[0]);
  1436. X    exit(0);
  1437. X}
  1438. X
  1439. X#else /*} defined(DBM) || defined(NDBM) {*/
  1440. X
  1441. X#include <fcntl.h>
  1442. X#include "pwd.h"
  1443. X#ifdef    BSD
  1444. X#include <strings.h>
  1445. X#define    strchr    index
  1446. X#define    strrchr    rindex
  1447. X#else
  1448. X#include <string.h>
  1449. X#endif
  1450. X
  1451. X#ifdef    DBM
  1452. X#include <dbm.h>
  1453. X#endif
  1454. X#ifdef    NDBM
  1455. X#include <ndbm.h>
  1456. X#include <grp.h>
  1457. X#include "shadow.h"
  1458. X
  1459. XDBM    *pw_dbm;
  1460. XDBM    *gr_dbm;
  1461. XDBM    *sp_dbm;
  1462. XDBM    *sgr_dbm;
  1463. Xchar    *fgetsx();
  1464. X#endif
  1465. X
  1466. Xchar    *CANT_OPEN =    "%s: cannot open file %s\n";
  1467. Xchar    *CANT_OVERWRITE = "%s: cannot overwrite file %s\n";
  1468. X#ifdef    DBM
  1469. Xchar    *CANT_CREATE =    "%s: cannot create %s\n";
  1470. X#endif
  1471. Xchar    *DBM_OPEN_ERR =    "%s: cannot open DBM files for %s\n";
  1472. Xchar    *PARSE_ERR =    "%s: error parsing line\n\"%s\"\n";
  1473. Xchar    *LINE_TOO_LONG = "%s: the beginning with \"%.16s ...\" is too long\n";
  1474. Xchar    *ADD_REC =    "adding record for name \"%s\"\n";
  1475. Xchar    *ADD_REC_ERR =    "%s: error adding record for \"%s\"\n";
  1476. Xchar    *INFO =        "added %d entries, longest was %d\n";
  1477. X#ifdef    NDBM
  1478. Xchar    *USAGE =    "Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n";
  1479. X#else
  1480. Xchar    *USAGE =    "Usage: %s [ -vf ] file\n";
  1481. X#endif
  1482. X
  1483. Xchar    *Progname;
  1484. Xint    vflg = 0;
  1485. Xint    fflg = 0;
  1486. X#ifdef    NDBM
  1487. Xint    gflg = 0;
  1488. Xint    sflg = 0;
  1489. Xint    pflg = 0;
  1490. X#endif
  1491. X
  1492. Xvoid    usage();
  1493. X
  1494. Xextern    char    *malloc();
  1495. Xextern    struct    passwd    *sgetpwent();
  1496. Xextern    int    pw_dbm_update();
  1497. X#ifdef    NDBM
  1498. Xextern    struct    group    *sgetgrent();
  1499. Xextern    struct    spwd    *sgetspent();
  1500. Xextern    struct    sgrp    *sgetsgent();
  1501. Xextern    int    sp_dbm_update();
  1502. Xextern    int    gr_dbm_update();
  1503. Xextern    int    sgr_dbm_update();
  1504. X#endif
  1505. X
  1506. X/*
  1507. X * mkpasswd - create DBM files for /etc/passwd-like input file
  1508. X *
  1509. X * mkpasswd takes an an argument the name of a file in /etc/passwd format
  1510. X * and creates a DBM file keyed by user ID and name.  The output files have
  1511. X * the same name as the input file, with .dir and .pag appended.
  1512. X *
  1513. X * if NDBM is defined this command will also create look-aside files for
  1514. X * /etc/group, /etc/shadow, and /etc/gshadow.
  1515. X */
  1516. X
  1517. Xint
  1518. Xmain (argc, argv)
  1519. Xint    argc;
  1520. Xchar    **argv;
  1521. X{
  1522. X    extern    int    optind;
  1523. X    extern    char    *optarg;
  1524. X    FILE    *fp;            /* File pointer for input file        */
  1525. X    char    *file;            /* Name of input file                 */
  1526. X    char    *dir;            /* Name of .dir file                  */
  1527. X    char    *pag;            /* Name of .pag file                  */
  1528. X    char    *cp;            /* Temporary character pointer        */
  1529. X    int    flag;            /* Flag for command line option       */
  1530. X#ifdef    DBM
  1531. X    int    fd;            /* File descriptor of open DBM file   */
  1532. X#endif
  1533. X    int    cnt = 0;        /* Number of entries in database      */
  1534. X    int    longest = 0;        /* Longest entry in database          */
  1535. X    int    len;            /* Length of input line               */
  1536. X    int    errors = 0;        /* Count of errors processing file    */
  1537. X    char    buf[BUFSIZ*8];        /* Input line from file               */
  1538. X    struct    passwd    *passwd;    /* Pointer to password file entry     */
  1539. X#ifdef    NDBM
  1540. X    struct    group    *group;        /* Pointer to group file entry        */
  1541. X    struct    spwd    *shadow;    /* Pointer to shadow passwd entry     */
  1542. X    struct    sgrp    *gshadow;    /* Pointer to shadow group entry      */
  1543. X    DBM    *dbm;            /* Pointer to new NDBM files          */
  1544. X    DBM    *dbm_open();        /* Function to open NDBM files        */
  1545. X#endif
  1546. X
  1547. X    /*
  1548. X     * Figure out what my name is.  I will use this later ...
  1549. X     */
  1550. X
  1551. X    if (Progname = strrchr (argv[0], '/'))
  1552. X        Progname++;
  1553. X    else
  1554. X        Progname = argv[0];
  1555. X
  1556. X    /*
  1557. X     * Figure out what the flags might be ...
  1558. X     */
  1559. X
  1560. X#ifdef    NDBM
  1561. X    while ((flag = getopt (argc, argv, "fvpgs")) != EOF)
  1562. X#else
  1563. X    while ((flag = getopt (argc, argv, "fv")) != EOF)
  1564. X#endif
  1565. X    {
  1566. X        switch (flag) {
  1567. X            case 'v':
  1568. X                vflg++;
  1569. X                break;
  1570. X            case 'f':
  1571. X                fflg++;
  1572. X                break;
  1573. X#ifdef    NDBM
  1574. X            case 'g':
  1575. X                gflg++;
  1576. X                if (pflg)
  1577. X                    usage ();
  1578. X
  1579. X                break;
  1580. X            case 's':
  1581. X                sflg++;
  1582. X                break;
  1583. X            case 'p':
  1584. X                pflg++;
  1585. X                if (gflg)
  1586. X                    usage ();
  1587. X
  1588. X                break;
  1589. X#endif
  1590. X            default:
  1591. X                usage ();
  1592. X        }
  1593. X    }
  1594. X
  1595. X#ifdef NDBM
  1596. X    /*
  1597. X     * Backwards compatibility fix for -p flag ...
  1598. X     */
  1599. X
  1600. X    if (! sflg && ! gflg)
  1601. X        pflg++;
  1602. X#endif
  1603. X
  1604. X    /*
  1605. X     * The last and only remaining argument must be the file name
  1606. X     */
  1607. X
  1608. X    if (argc - 1 != optind)
  1609. X        usage ();
  1610. X
  1611. X    file = argv[optind];
  1612. X
  1613. X    if (! (fp = fopen (file, "r"))) {
  1614. X        fprintf (stderr, CANT_OPEN, Progname, file);
  1615. X        exit (1);
  1616. X    }
  1617. X
  1618. X    /*
  1619. X     * Make the filenames for the two DBM files.
  1620. X     */
  1621. X
  1622. X    dir = malloc (strlen (file) + 5);    /* space for .dir file */
  1623. X    strcat (strcpy (dir, file), ".dir");
  1624. X
  1625. X    pag = malloc (strlen (file) + 5);    /* space for .pag file */
  1626. X    strcat (strcpy (pag, file), ".pag");
  1627. X
  1628. X    /*
  1629. X     * Remove existing files if requested.
  1630. X     */
  1631. X
  1632. X    if (fflg) {
  1633. X        (void) unlink (dir);
  1634. X        (void) unlink (pag);
  1635. X    }
  1636. X
  1637. X    /*
  1638. X     * Create the two DBM files - it is an error for these files
  1639. X     * to have existed already.
  1640. X     */
  1641. X
  1642. X    if (access (dir, 0) == 0) {
  1643. X        fprintf (stderr, CANT_OVERWRITE, Progname, dir);
  1644. X        exit (1);
  1645. X    }
  1646. X    if (access (pag, 0) == 0) {
  1647. X        fprintf (stderr, CANT_OVERWRITE, Progname, pag);
  1648. X        exit (1);
  1649. X    }
  1650. X
  1651. X#ifdef    NDBM
  1652. X    if (sflg)
  1653. X        umask (077);
  1654. X    else
  1655. X#endif
  1656. X    umask (0);
  1657. X#ifdef    DBM
  1658. X    if ((fd = open (dir, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) {
  1659. X        fprintf (stderr, CANT_CREATE, Progname, dir);
  1660. X        exit (1);
  1661. X    } else
  1662. X        close (fd);
  1663. X
  1664. X    if ((fd = open (pag, O_RDWR|O_CREAT|O_EXCL, 0644)) == -1) {
  1665. X        fprintf (stderr, CANT_CREATE, Progname, pag);
  1666. X        unlink (dir);
  1667. X        exit (1);
  1668. X    } else
  1669. X        close (fd);
  1670. X#endif
  1671. X
  1672. X    /*
  1673. X     * Now the DBM database gets initialized
  1674. X     */
  1675. X
  1676. X#ifdef    DBM
  1677. X    if (dbminit (file) == -1) {
  1678. X        fprintf (stderr, DBM_OPEN_ERR, Progname, file);
  1679. X        exit (1);
  1680. X    }
  1681. X#endif
  1682. X#ifdef    NDBM
  1683. X    if (! (dbm = dbm_open (file, O_RDWR|O_CREAT, 0644))) {
  1684. X        fprintf (stderr, DBM_OPEN_ERR, Progname, file);
  1685. X        exit (1);
  1686. X    }
  1687. X    if (gflg) {
  1688. X        if (sflg)
  1689. X            sgr_dbm = dbm;
  1690. X        else
  1691. X            gr_dbm = dbm;
  1692. X    } else {
  1693. X        if (sflg)
  1694. X            sp_dbm = dbm;
  1695. X        else
  1696. X            pw_dbm = dbm;
  1697. X    }
  1698. X#endif
  1699. X
  1700. X    /*
  1701. X     * Read every line in the password file and convert it into a
  1702. X     * data structure to be put in the DBM database files.
  1703. X     */
  1704. X
  1705. X#ifdef    NDBM
  1706. X    while (fgetsx (buf, BUFSIZ, fp) != NULL)
  1707. X#else
  1708. X    while (fgets (buf, BUFSIZ, fp) != NULL)
  1709. X#endif
  1710. X    {
  1711. X
  1712. X        /*
  1713. X         * Get the next line and strip off the trailing newline
  1714. X         * character.
  1715. X         */
  1716. X
  1717. X        buf[sizeof buf - 1] = '\0';
  1718. X        if (! (cp = strchr (buf, '\n'))) {
  1719. X            fprintf (stderr, LINE_TOO_LONG, Progname, buf);
  1720. X            exit (1);
  1721. X        }
  1722. X        *cp = '\0';
  1723. X        len = strlen (buf);
  1724. X
  1725. X        /*
  1726. X         * Parse the password file line into a (struct passwd).
  1727. X         * Erroneous lines cause error messages, but that's
  1728. X         * all.  YP lines are ignored completely.
  1729. X         */
  1730. X
  1731. X        if (buf[0] == '-' || buf[0] == '+')
  1732. X            continue;
  1733. X
  1734. X#ifdef    DBM
  1735. X        if (! (passwd = sgetpwent (buf)))
  1736. X#endif
  1737. X#ifdef    NDBM
  1738. X        if (! (((! sflg && pflg) && (passwd = sgetpwent (buf)))
  1739. X            || ((sflg && pflg) && (shadow = sgetspent (buf)))
  1740. X            || ((! sflg && gflg) && (group = sgetgrent (buf)))
  1741. X            || ((sflg && gflg) && (gshadow = sgetsgent (buf)))))
  1742. X#endif
  1743. X        {
  1744. X            fprintf (stderr, PARSE_ERR, Progname, buf);
  1745. X            errors++;
  1746. X            continue;
  1747. X        }
  1748. X#ifdef    DBM
  1749. X        if (vflg)
  1750. X            printf (ADD_REC, passwd->pw_name);
  1751. X
  1752. X        if (! pw_dbm_update (passwd))
  1753. X            fprintf (stderr, ADD_REC_ERR,
  1754. X                Progname, passwd->pw_name);
  1755. X#endif
  1756. X#ifdef    NDBM
  1757. X        if (vflg) {
  1758. X            if (!sflg && pflg) printf (ADD_REC, passwd->pw_name);
  1759. X            if (sflg && pflg) printf (ADD_REC, shadow->sp_namp);
  1760. X            if (!sflg && gflg) printf (ADD_REC, group->gr_name);
  1761. X            if (sflg && gflg) printf (ADD_REC, gshadow->sg_name);
  1762. X        }
  1763. X        if (! sflg && pflg && ! pw_dbm_update (passwd))
  1764. X            fprintf (stderr, ADD_REC_ERR,
  1765. X                Progname, passwd->pw_name);
  1766. X
  1767. X        if (sflg && pflg && ! sp_dbm_update (shadow))
  1768. X            fprintf (stderr, ADD_REC_ERR,
  1769. X                Progname, shadow->sp_namp);
  1770. X
  1771. X        if (! sflg && gflg && ! gr_dbm_update (group))
  1772. X            fprintf (stderr, ADD_REC_ERR,
  1773. X                Progname, group->gr_name);
  1774. X
  1775. X        if (sflg && gflg && ! sgr_dbm_update (gshadow))
  1776. X            fprintf (stderr, ADD_REC_ERR,
  1777. X                Progname, gshadow->sg_name);
  1778. X#endif
  1779. X
  1780. X        /*
  1781. X         * Update the longest record and record count
  1782. X         */
  1783. X
  1784. X        if (len > longest)
  1785. X            longest = len;
  1786. X        cnt++;
  1787. X    }
  1788. X
  1789. X    /*
  1790. X     * Tell the user how things went ...
  1791. X     */
  1792. X
  1793. X    if (vflg)
  1794. X        printf (INFO, cnt, longest);
  1795. X
  1796. X    exit (errors);
  1797. X    /*NOTREACHED*/
  1798. X}
  1799. X
  1800. X/*
  1801. X * usage - print error message and exit
  1802. X */
  1803. X
  1804. Xvoid
  1805. Xusage ()
  1806. X{
  1807. X    fprintf (stderr, USAGE, Progname);
  1808. X    exit (1);
  1809. X    /*NOTREACHED*/
  1810. X}
  1811. X#endif /*} defined(DBM) || defined(NDBM) */
  1812. END_OF_FILE
  1813.   if test 8625 -ne `wc -c <'mkpasswd.c'`; then
  1814.     echo shar: \"'mkpasswd.c'\" unpacked with wrong size!
  1815.   fi
  1816.   # end of 'mkpasswd.c'
  1817. fi
  1818. if test -f 'port.c' -a "${1}" != "-c" ; then 
  1819.   echo shar: Will not clobber existing file \"'port.c'\"
  1820. else
  1821.   echo shar: Extracting \"'port.c'\" \(8978 characters\)
  1822.   sed "s/^X//" >'port.c' <<'END_OF_FILE'
  1823. X/*
  1824. X * Copyright 1989, 1990, 1991, John F. Haugh II
  1825. X * All rights reserved.
  1826. X *
  1827. X * Permission is granted to copy and create derivative works for any
  1828. X * non-commercial purpose, provided this copyright notice is preserved
  1829. X * in all copies of source code, or included in human readable form
  1830. X * and conspicuously displayed on all copies of object code or
  1831. X * distribution media.
  1832. X */
  1833. X
  1834. X#include <stdio.h>
  1835. X#include <time.h>
  1836. X#include <sys/types.h>
  1837. X#include <ctype.h>
  1838. X#include <errno.h>
  1839. X#ifndef    BSD
  1840. X#include <string.h>
  1841. X#else
  1842. X#include <strings.h>
  1843. X#define    strchr    index
  1844. X#define    strrchr    rindex
  1845. X#endif
  1846. X#include "port.h"
  1847. X
  1848. X#ifndef    lint
  1849. Xstatic    char    _sccsid[] = "@(#)port.c    3.1    08:59:32    2/8/91";
  1850. X#endif
  1851. X
  1852. Xextern    int    errno;
  1853. X
  1854. Xstatic    FILE    *ports;
  1855. X
  1856. X/*
  1857. X * setttyent - open /etc/porttime file or rewind
  1858. X *
  1859. X *    the /etc/porttime file is rewound if already open, or
  1860. X *    opened for reading.
  1861. X */
  1862. X
  1863. Xvoid
  1864. Xsetttyent ()
  1865. X{
  1866. X    if (ports)
  1867. X        rewind (ports);
  1868. X    else 
  1869. X        ports = fopen (PORTS, "r");
  1870. X}
  1871. X
  1872. X/*
  1873. X * endttyent - close the /etc/porttime file
  1874. X *
  1875. X *    the /etc/porttime file is closed and the ports variable set
  1876. X *    to NULL to indicate that the /etc/porttime file is no longer
  1877. X *    open.
  1878. X */
  1879. X
  1880. Xvoid
  1881. Xendttyent ()
  1882. X{
  1883. X    if (ports)
  1884. X        fclose (ports);
  1885. X
  1886. X    ports = (FILE *) 0;
  1887. X}
  1888. X
  1889. X/*
  1890. X * getttyent - read a single entry from /etc/porttime
  1891. X *
  1892. X *    the next line in /etc/porttime is converted to a (struct port)
  1893. X *    and a pointer to a static (struct port) is returned to the
  1894. X *    invoker.  NULL is returned on either EOF or error.  errno is
  1895. X *    set to EINVAL on error to distinguish the two conditions.
  1896. X */
  1897. X
  1898. Xstruct port *
  1899. Xgetttyent ()
  1900. X{
  1901. X    static    struct    port    port;    /* static struct to point to         */
  1902. X    static    char    buf[BUFSIZ];    /* some space for stuff              */
  1903. X    static    char    *ttys[PORT_TTY+1]; /* some pointers to tty names     */
  1904. X    static    char    *users[PORT_IDS+1]; /* some pointers to user ids     */
  1905. X    static    struct    pt_time    times[PORT_TIMES+1]; /* time ranges          */
  1906. X    char    *cp;            /* pointer into line                 */
  1907. X    int    time;            /* scratch time of day               */
  1908. X    int    i, j;
  1909. X    int    saveerr = errno;    /* errno value on entry              */
  1910. X
  1911. X    /*
  1912. X     * If the ports file is not open, open the file.  Do not rewind
  1913. X     * since we want to search from the beginning each time.
  1914. X     */
  1915. X
  1916. X    if (! ports)
  1917. X        setttyent ();
  1918. X
  1919. X    if (! ports) {
  1920. X        errno = saveerr;
  1921. X        return 0;
  1922. X    }
  1923. X
  1924. X    /*
  1925. X     * Common point for beginning a new line -
  1926. X     *
  1927. X     *    - read a line, and NUL terminate
  1928. X     *    - skip lines which begin with '#'
  1929. X     *    - parse off the tty names
  1930. X     *    - parse off a list of user names
  1931. X     *    - parse off a list of days and times
  1932. X     */
  1933. X
  1934. Xagain:
  1935. X
  1936. X    /*
  1937. X     * Get the next line and remove the last character, which
  1938. X     * is a '\n'.  Lines which begin with '#' are all ignored.
  1939. X     */
  1940. X
  1941. X    if (fgets (buf, BUFSIZ, ports) == 0) {
  1942. X        errno = saveerr;
  1943. X        return 0;
  1944. X    }
  1945. X    if (buf[0] == '#')
  1946. X        goto again;
  1947. X
  1948. X    /*
  1949. X     * Get the name of the TTY device.  It is the first colon
  1950. X     * separated field, and is the name of the TTY with no
  1951. X     * leading "/dev".  The entry '*' is used to specify all
  1952. X     * TTY devices.
  1953. X     */
  1954. X
  1955. X    buf[strlen (buf) - 1] = 0;
  1956. X
  1957. X    port.pt_names = ttys;
  1958. X    for (cp = buf, j = 0;j < PORT_TTY;j++) {
  1959. X        port.pt_names[j] = cp;
  1960. X        while (*cp && *cp != ':' && *cp != ',')
  1961. X            cp++;
  1962. X
  1963. X        if (! *cp)
  1964. X            goto again;    /* line format error */
  1965. X
  1966. X        if (*cp == ':')        /* end of tty name list */
  1967. X            break;
  1968. X
  1969. X        if (*cp == ',')        /* end of current tty name */
  1970. X            *cp++ = '\0';
  1971. X    }
  1972. X    *cp++ = 0;
  1973. X    port.pt_names[j + 1] = (char *) 0;
  1974. X
  1975. X    /*
  1976. X     * Get the list of user names.  It is the second colon
  1977. X     * separated field, and is a comma separated list of user
  1978. X     * names.  The entry '*' is used to specify all usernames.
  1979. X     * The last entry in the list is a (char *) 0 pointer.
  1980. X     */
  1981. X
  1982. X    if (*cp != ':') {
  1983. X        port.pt_users = users;
  1984. X        port.pt_users[0] = cp;
  1985. X
  1986. X        for (j = 1;*cp != ':';cp++) {
  1987. X            if (*cp == ',' && j < PORT_IDS) {
  1988. X                *cp++ = 0;
  1989. X                port.pt_users[j++] = cp;
  1990. X            }
  1991. X        }
  1992. X        port.pt_users[j] = 0;
  1993. X    } else
  1994. X        port.pt_users = 0;
  1995. X
  1996. X    if (*cp != ':')
  1997. X        goto again;
  1998. X
  1999. X    *cp++ = 0;
  2000. X
  2001. X    /*
  2002. X     * Get the list of valid times.  The times field is the third
  2003. X     * colon separated field and is a list of days of the week and
  2004. X     * times during which this port may be used by this user.  The
  2005. X     * valid days are 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', and 'Sa'.
  2006. X     *
  2007. X     * In addition, the value 'Al' represents all 7 days, and 'Wk'
  2008. X     * represents the 5 weekdays.
  2009. X     *
  2010. X     * Times are given as HHMM-HHMM.  The ending time may be before
  2011. X     * the starting time.  Days are presumed to wrap at 0000.
  2012. X     */
  2013. X
  2014. X    if (*cp == '\0') {
  2015. X        port.pt_times = 0;
  2016. X        return &port;
  2017. X    }
  2018. X
  2019. X    port.pt_times = times;
  2020. X
  2021. X    /*
  2022. X     * Get the next comma separated entry
  2023. X     */
  2024. X
  2025. X    for (j = 0;*cp && j < PORT_TIMES;j++) {
  2026. X
  2027. X        /*
  2028. X         * Start off with no days of the week
  2029. X         */
  2030. X
  2031. X        port.pt_times[j].t_days = 0;
  2032. X
  2033. X        /*
  2034. X         * Check each two letter sequence to see if it is
  2035. X         * one of the abbreviations for the days of the
  2036. X         * week or the other two values.
  2037. X         */
  2038. X
  2039. X        for (i = 0;cp[i] && cp[i + 1] && isalpha (cp[i]);i += 2) {
  2040. X            switch ((cp[i] << 8) | (cp[i + 1])) {
  2041. X                case ('S' << 8) | 'u':
  2042. X                    port.pt_times[j].t_days |= 01;
  2043. X                    break;
  2044. X                case ('M' << 8) | 'o':
  2045. X                    port.pt_times[j].t_days |= 02;
  2046. X                    break;
  2047. X                case ('T' << 8) | 'u':
  2048. X                    port.pt_times[j].t_days |= 04;
  2049. X                    break;
  2050. X                case ('W' << 8) | 'e':
  2051. X                    port.pt_times[j].t_days |= 010;
  2052. X                    break;
  2053. X                case ('T' << 8) | 'h':
  2054. X                    port.pt_times[j].t_days |= 020;
  2055. X                    break;
  2056. X                case ('F' << 8) | 'r':
  2057. X                    port.pt_times[j].t_days |= 040;
  2058. X                    break;
  2059. X                case ('S' << 8) | 'a':
  2060. X                    port.pt_times[j].t_days |= 0100;
  2061. X                    break;
  2062. X                case ('W' << 8) | 'k':
  2063. X                    port.pt_times[j].t_days |= 076;
  2064. X                    break;
  2065. X                case ('A' << 8) | 'l':
  2066. X                    port.pt_times[j].t_days |= 0177;
  2067. X                    break;
  2068. X                default:
  2069. X                    errno = EINVAL;
  2070. X                    return 0;
  2071. X            }
  2072. X        }
  2073. X
  2074. X        /*
  2075. X         * The default is 'Al' if no days were seen.
  2076. X         */
  2077. X
  2078. X        if (i == 0)
  2079. X            port.pt_times[j].t_days = 0177;
  2080. X
  2081. X        /*
  2082. X         * The start and end times are separated from each
  2083. X         * other by a '-'.  The times are four digit numbers
  2084. X         * representing the times of day.
  2085. X         */
  2086. X
  2087. X        for (time = 0;cp[i] && isdigit (cp[i]);i++)
  2088. X            time = time * 10 + cp[i] - '0';
  2089. X
  2090. X        if (cp[i] != '-' || time > 2400 || time % 100 > 59)
  2091. X            goto again;
  2092. X        port.pt_times[j].t_start = time;
  2093. X        cp = cp + i + 1;
  2094. X
  2095. X        for (time = i = 0;cp[i] && isdigit (cp[i]);i++)
  2096. X            time = time * 10 + cp[i] - '0';
  2097. X
  2098. X        if ((cp[i] != ',' && cp[i]) || time > 2400 || time % 100 > 59)
  2099. X            goto again;
  2100. X
  2101. X        port.pt_times[j].t_end = time;
  2102. X        cp = cp + i + 1;
  2103. X    }
  2104. X
  2105. X    /*
  2106. X     * The end of the list is indicated by a pair of -1's for the
  2107. X     * start and end times.
  2108. X     */
  2109. X
  2110. X    port.pt_times[j].t_start = port.pt_times[j].t_end = -1;
  2111. X
  2112. X    return &port;
  2113. X}
  2114. X
  2115. X/*
  2116. X * getttyuser - get ports information for user and tty
  2117. X *
  2118. X *    getttyuser() searches the ports file for an entry with a TTY
  2119. X *    and user field both of which match the supplied TTY and
  2120. X *    user name.  The file is searched from the beginning, so the
  2121. X *    entries are treated as an ordered list.
  2122. X */
  2123. X
  2124. Xstruct port *
  2125. Xgetttyuser (tty, user)
  2126. Xchar    *tty;
  2127. Xchar    *user;
  2128. X{
  2129. X    int    i, j;
  2130. X    struct    port    *port;
  2131. X
  2132. X    setttyent ();
  2133. X
  2134. X    while (port = getttyent ()) {
  2135. X        if (port->pt_names == 0 || port->pt_users == 0)
  2136. X            continue;
  2137. X
  2138. X        for (i = 0;port->pt_names[i];i++)
  2139. X            if (strcmp (port->pt_names[i], tty) == 0 ||
  2140. X                    strcmp (port->pt_names[i], "*") == 0)
  2141. X                break;
  2142. X
  2143. X        if (port->pt_names[i] == 0)
  2144. X            continue;
  2145. X
  2146. X        for (j = 0;port->pt_users[j];j++)
  2147. X            if (strcmp (user, port->pt_users[j]) == 0 ||
  2148. X                    strcmp (port->pt_users[j], "*") == 0)
  2149. X                break;
  2150. X
  2151. X        if (port->pt_users[j] != 0)
  2152. X            break;
  2153. X    }
  2154. X    endttyent ();
  2155. X    return port;
  2156. X}
  2157. X
  2158. X/*
  2159. X * isttytime - tell if a given user may login at a particular time
  2160. X *
  2161. X *    isttytime searches the ports file for an entry which matches
  2162. X *    the user name and TTY given.
  2163. X */
  2164. X
  2165. Xint
  2166. Xisttytime (id, port, clock)
  2167. Xchar    *id;
  2168. Xchar    *port;
  2169. Xlong    clock;
  2170. X{
  2171. X    int    i;
  2172. X    int    time;
  2173. X    struct    port    *pp;
  2174. X    struct    tm    *tm,
  2175. X            *localtime();
  2176. X
  2177. X    /*
  2178. X     * Try to find a matching entry for this user.  Default to
  2179. X     * letting the user in - there are pleny of ways to have an
  2180. X     * entry to match all users.
  2181. X     */
  2182. X
  2183. X    if (! (pp = getttyuser (port, id)))
  2184. X        return 1;
  2185. X
  2186. X    /*
  2187. X     * The entry is there, but has not time entries - don't
  2188. X     * ever let them login.
  2189. X     */
  2190. X
  2191. X    if (pp->pt_times == 0)
  2192. X        return 0;
  2193. X
  2194. X    /*
  2195. X     * The current time is converted to HHMM format for
  2196. X     * comparision against the time values in the TTY entry.
  2197. X     */
  2198. X
  2199. X    tm = localtime (&clock);
  2200. X    time = tm->tm_hour * 100 + tm->tm_min;
  2201. X
  2202. X    /*
  2203. X     * Each time entry is compared against the current
  2204. X     * time.  For entries with the start after the end time,
  2205. X     * the comparision is made so that the time is between
  2206. X     * midnight and either the start or end time.
  2207. X     */
  2208. X
  2209. X    for (i = 0;pp->pt_times[i].t_start != -1;i++) {
  2210. X        if (! (pp->pt_times[i].t_days & PORT_DAY(tm->tm_wday)))
  2211. X            continue;
  2212. X
  2213. X        if (pp->pt_times[i].t_start <= pp->pt_times[i].t_end) {
  2214. X            if (time >= pp->pt_times[i].t_start &&
  2215. X                    time <= pp->pt_times[i].t_end)
  2216. X                return 1;
  2217. X        } else {
  2218. X            if (time >= pp->pt_times[i].t_start ||
  2219. X                    time <= pp->pt_times[i].t_end)
  2220. X                return 1;
  2221. X        }
  2222. X    }
  2223. X
  2224. X    /*
  2225. X     * No matching time entry was found, user shouldn't
  2226. X     * be let in right now.
  2227. X     */
  2228. X
  2229. X    return 0;
  2230. X}
  2231. END_OF_FILE
  2232.   if test 8978 -ne `wc -c <'port.c'`; then
  2233.     echo shar: \"'port.c'\" unpacked with wrong size!
  2234.   fi
  2235.   # end of 'port.c'
  2236. fi
  2237. if test -f 'shadow.c' -a "${1}" != "-c" ; then 
  2238.   echo shar: Will not clobber existing file \"'shadow.c'\"
  2239. else
  2240.   echo shar: Extracting \"'shadow.c'\" \(5851 characters\)
  2241.   sed "s/^X//" >'shadow.c' <<'END_OF_FILE'
  2242. X/*
  2243. X * Copyright 1989, 1990, John F. Haugh II
  2244. X * All rights reserved.
  2245. X *
  2246. X * Permission is granted to copy and create derivative works for any
  2247. X * non-commercial purpose, provided this copyright notice is preserved
  2248. X * in all copies of source code, or included in human readable form
  2249. X * and conspicuously displayed on all copies of object code or
  2250. X * distribution media.
  2251. X */
  2252. X
  2253. X#include "shadow.h"
  2254. X#include "config.h"
  2255. X#include <stdio.h>
  2256. X
  2257. X#ifndef    BSD
  2258. X#include <string.h>
  2259. X#include <memory.h>
  2260. X#else
  2261. X#include <strings.h>
  2262. X#define    strchr    index
  2263. X#define    strrchr    rindex
  2264. X#endif
  2265. X
  2266. X#ifdef    NDBM
  2267. X#include <ndbm.h>
  2268. X#include <fcntl.h>
  2269. XDBM    *sp_dbm;
  2270. Xint    sp_dbm_mode = -1;
  2271. Xstatic    int    dbmopened;
  2272. Xstatic    int    dbmerror;
  2273. X#endif
  2274. X
  2275. X
  2276. X#ifndef    lint
  2277. Xstatic    char    sccsid[] = "@(#)shadow.c    3.9    08:44:32    9/12/91";
  2278. X#endif
  2279. X
  2280. Xstatic    FILE    *shadow;
  2281. Xstatic    char    spwbuf[BUFSIZ];
  2282. Xstatic    struct    spwd    spwd;
  2283. X
  2284. X#define    FIELDS    9
  2285. X#define    OFIELDS    5
  2286. X
  2287. Xvoid
  2288. Xsetspent ()
  2289. X{
  2290. X    if (shadow)
  2291. X        rewind (shadow);
  2292. X    else
  2293. X        shadow = fopen (SHADOW, "r");
  2294. X
  2295. X    /*
  2296. X     * Attempt to open the DBM files if they have never been opened
  2297. X     * and an error has never been returned.
  2298. X     */
  2299. X
  2300. X#ifdef NDBM
  2301. X    if (! dbmerror && ! dbmopened) {
  2302. X        int    mode;
  2303. X        char    dbmfiles[BUFSIZ];
  2304. X
  2305. X        strcpy (dbmfiles, SHADOW);
  2306. X        strcat (dbmfiles, ".pag");
  2307. X
  2308. X        if (sp_dbm_mode == -1)
  2309. X            mode = O_RDWR;
  2310. X        else
  2311. X            mode = (sp_dbm_mode == O_RDWR) ? O_RDWR:O_RDONLY;
  2312. X
  2313. X        if (! (sp_dbm = dbm_open (SHADOW, mode, 0)))
  2314. X            dbmerror = 1;
  2315. X        else
  2316. X            dbmopened = 1;
  2317. X    }
  2318. X#endif
  2319. X}
  2320. X
  2321. Xvoid
  2322. Xendspent ()
  2323. X{
  2324. X    if (shadow)
  2325. X        (void) fclose (shadow);
  2326. X
  2327. X    shadow = (FILE *) 0;
  2328. X#ifdef    NDBM
  2329. X    if (dbmopened && sp_dbm) {
  2330. X        dbm_close (sp_dbm);
  2331. X        sp_dbm = 0;
  2332. X    }
  2333. X    dbmopened = 0;
  2334. X    dbmerror = 0;
  2335. X#endif
  2336. X}
  2337. X
  2338. Xstruct spwd *
  2339. Xsgetspent (string)
  2340. Xchar    *string;
  2341. X{
  2342. X    char    *fields[FIELDS];
  2343. X    char    *cp;
  2344. X    char    *cpp;
  2345. X    int    atoi ();
  2346. X    long    atol ();
  2347. X    int    i;
  2348. X
  2349. X    strncpy (spwbuf, string, BUFSIZ-1);
  2350. X    spwbuf[BUFSIZ-1] = '\0';
  2351. X
  2352. X    if (cp = strrchr (spwbuf, '\n'))
  2353. X        *cp = '\0';
  2354. X
  2355. X    for (cp = spwbuf, i = 0;*cp && i < FIELDS;i++) {
  2356. X        fields[i] = cp;
  2357. X        while (*cp && *cp != ':')
  2358. X            cp++;
  2359. X
  2360. X        if (*cp)
  2361. X            *cp++ = '\0';
  2362. X    }
  2363. X    if (i == (FIELDS-1))
  2364. X        fields[i++] = cp;
  2365. X
  2366. X    if (*cp || (i != FIELDS && i != OFIELDS))
  2367. X        return 0;
  2368. X
  2369. X    spwd.sp_namp = fields[0];
  2370. X    spwd.sp_pwdp = fields[1];
  2371. X
  2372. X    if ((spwd.sp_lstchg = strtol (fields[2], &cpp, 10)) == 0 && *cpp)
  2373. X        return 0;
  2374. X    else if (fields[2][0] == '\0')
  2375. X        spwd.sp_lstchg = -1;
  2376. X
  2377. X    if ((spwd.sp_min = strtol (fields[3], &cpp, 10)) == 0 && *cpp)
  2378. X        return 0;
  2379. X    else if (fields[3][0] == '\0')
  2380. X        spwd.sp_min = -1;
  2381. X
  2382. X    if ((spwd.sp_max = strtol (fields[4], &cpp, 10)) == 0 && *cpp)
  2383. X        return 0;
  2384. X    else if (fields[4][0] == '\0')
  2385. X        spwd.sp_max = -1;
  2386. X
  2387. X    if (i == OFIELDS) {
  2388. X        spwd.sp_warn = spwd.sp_inact = spwd.sp_expire =
  2389. X            spwd.sp_flag = -1;
  2390. X
  2391. X        return &spwd;
  2392. X    }
  2393. X    if ((spwd.sp_warn = strtol (fields[5], &cpp, 10)) == 0 && *cpp)
  2394. X        return 0;
  2395. X    else if (fields[5][0] == '\0')
  2396. X        spwd.sp_warn = -1;
  2397. X
  2398. X    if ((spwd.sp_inact = strtol (fields[6], &cpp, 10)) == 0 && *cpp)
  2399. X        return 0;
  2400. X    else if (fields[6][0] == '\0')
  2401. X        spwd.sp_inact = -1;
  2402. X
  2403. X    if ((spwd.sp_expire = strtol (fields[7], &cpp, 10)) == 0 && *cpp)
  2404. X        return 0;
  2405. X    else if (fields[7][0] == '\0')
  2406. X        spwd.sp_expire = -1;
  2407. X
  2408. X    if ((spwd.sp_flag = strtol (fields[8], &cpp, 10)) == 0 && *cpp)
  2409. X        return 0;
  2410. X    else if (fields[8][0] == '\0')
  2411. X        spwd.sp_flag = -1;
  2412. X
  2413. X    return (&spwd);
  2414. X}
  2415. X
  2416. Xstruct spwd
  2417. X*fgetspent (fp)
  2418. XFILE    *fp;
  2419. X{
  2420. X    char    buf[BUFSIZ];
  2421. X
  2422. X    if (! fp)
  2423. X        return (0);
  2424. X
  2425. X    if (fgets (buf, BUFSIZ, fp) == (char *) 0)
  2426. X        return (0);
  2427. X
  2428. X    return sgetspent (buf);
  2429. X}
  2430. X
  2431. Xstruct spwd
  2432. X*getspent ()
  2433. X{
  2434. X    if (! shadow)
  2435. X        setspent ();
  2436. X
  2437. X    return (fgetspent (shadow));
  2438. X}
  2439. X
  2440. Xstruct spwd
  2441. X*getspnam (name)
  2442. Xchar    *name;
  2443. X{
  2444. X    struct    spwd    *sp;
  2445. X#ifdef NDBM
  2446. X    datum    key;
  2447. X    datum    content;
  2448. X#endif
  2449. X
  2450. X    setspent ();
  2451. X
  2452. X#ifdef NDBM
  2453. X
  2454. X    /*
  2455. X     * If the DBM file are now open, create a key for this UID and
  2456. X     * try to fetch the entry from the database.  A matching record
  2457. X     * will be unpacked into a static structure and returned to
  2458. X     * the user.
  2459. X     */
  2460. X
  2461. X    if (dbmopened) {
  2462. X        key.dsize = strlen (name);
  2463. X        key.dptr = name;
  2464. X
  2465. X        content = dbm_fetch (sp_dbm, key);
  2466. X        if (content.dptr != 0) {
  2467. X            memcpy (spwbuf, content.dptr, content.dsize);
  2468. X            spw_unpack (spwbuf, content.dsize, &spwd);
  2469. X            return &spwd;
  2470. X        }
  2471. X    }
  2472. X#endif
  2473. X    while ((sp = getspent ()) != (struct spwd *) 0) {
  2474. X        if (strcmp (name, sp->sp_namp) == 0)
  2475. X            return (sp);
  2476. X    }
  2477. X    return (0);
  2478. X}
  2479. X
  2480. Xint
  2481. Xputspent (sp, fp)
  2482. Xstruct    spwd    *sp;
  2483. XFILE    *fp;
  2484. X{
  2485. X    int    errors = 0;
  2486. X
  2487. X    if (! fp || ! sp)
  2488. X        return -1;
  2489. X
  2490. X    if (fprintf (fp, "%s:%s:", sp->sp_namp, sp->sp_pwdp) < 0)
  2491. X        errors++;
  2492. X
  2493. X    if (sp->sp_lstchg != -1) {
  2494. X        if (fprintf (fp, "%ld:", sp->sp_lstchg) < 0)
  2495. X            errors++;
  2496. X    } else if (putc (':', fp) == EOF)
  2497. X        errors++;
  2498. X
  2499. X    if (sp->sp_min != -1) {
  2500. X        if (fprintf (fp, "%ld:", sp->sp_min) < 0)
  2501. X            errors++;
  2502. X    } else if (putc (':', fp) == EOF)
  2503. X        errors++;
  2504. X
  2505. X    if (sp->sp_max != -1) {
  2506. X        if (fprintf (fp, "%ld", sp->sp_max) < 0)
  2507. X            errors++;
  2508. X    }
  2509. X
  2510. X    /*
  2511. X     * See if the structure has any of the SVR4 fields in
  2512. X     * it.  If none of those fields have any data there is
  2513. X     * no reason to write them out since they will be filled
  2514. X     * in the same way when they are read back in.  Otherwise
  2515. X     * there is at least one SVR4 field that must be output.
  2516. X     */
  2517. X
  2518. X    if (sp->sp_warn == -1 && sp->sp_inact == -1 &&
  2519. X            sp->sp_expire == -1 && sp->sp_flag == -1) {
  2520. X        if (putc ('\n', fp) == EOF || errors)
  2521. X            return -1;
  2522. X        else
  2523. X            return 0;
  2524. X    } else if (putc (':', fp) == EOF)
  2525. X        errors++;
  2526. X
  2527. X    if (sp->sp_warn != -1) {
  2528. X        if (fprintf (fp, "%ld:", sp->sp_warn) < 0)
  2529. X            errors++;
  2530. X    } else if (putc (':', fp) == EOF)
  2531. X        errors++;
  2532. X
  2533. X    if (sp->sp_inact != -1) {
  2534. X        if (fprintf (fp, "%ld:", sp->sp_inact) < 0)
  2535. X            errors++;
  2536. X    } else if (putc (':', fp) == EOF)
  2537. X        errors++;
  2538. X
  2539. X    if (sp->sp_expire != -1) {
  2540. X        if (fprintf (fp, "%ld:", sp->sp_expire) < 0)
  2541. X            errors++;
  2542. X    } else if (putc (':', fp) == EOF)
  2543. X        errors++;
  2544. X
  2545. X    if (sp->sp_flag != -1) {
  2546. X        if (fprintf (fp, "%ld", sp->sp_flag) < 0)
  2547. X            errors++;
  2548. X    }
  2549. X    if (putc ('\n', fp) == EOF)
  2550. X        errors++;
  2551. X
  2552. X    if (errors)
  2553. X        return -1;
  2554. X    else
  2555. X        return 0;
  2556. X}
  2557. END_OF_FILE
  2558.   if test 5851 -ne `wc -c <'shadow.c'`; then
  2559.     echo shar: \"'shadow.c'\" unpacked with wrong size!
  2560.   fi
  2561.   # end of 'shadow.c'
  2562. fi
  2563. echo shar: End of archive 7 \(of 11\).
  2564. cp /dev/null ark7isdone
  2565. MISSING=""
  2566. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2567.     if test ! -f ark${I}isdone ; then
  2568.     MISSING="${MISSING} ${I}"
  2569.     fi
  2570. done
  2571. if test "${MISSING}" = "" ; then
  2572.     echo You have unpacked all 11 archives.
  2573.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2574. else
  2575.     echo You still must unpack the following archives:
  2576.     echo "        " ${MISSING}
  2577. fi
  2578. exit 0
  2579. exit 0 # Just in case...
  2580.